/******************************************************************************
 * Copyright (C) 2015  671643387@qq.com
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 *****************************************************************************/

#ifndef SHARED_NET_TCPSERVER_H_
#define SHARED_NET_TCPSERVER_H_

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif

#include <memory>
#include <string>
#include <boost/unordered_map.hpp>
#include <event2/util.h>
#include <event2/buffer.h>
#include <event2/bufferevent.h>
#include <event2/event.h>
#include "Shared/Global_Macros.h"
#include "Shared/Base/Mutex.h"
#include "Shared/Base/ThreadPool.h"
#include "Shared/Net/ServerSocket.h"


namespace Shared {
namespace Net {
    class Socket;
    class SocketEventHandlerFactory;
	class TcpThread;

    class TcpServer
    {
    public:
        const static int MAX_WORKERS = 0x80;

        TcpServer(SocketEventHandlerFactory *socketFactory, int priority = Thread::PRIO_NORMAL);
        ~TcpServer(void);

        bool start(const char *ip, int port, int backlog, int addtionalThreads = 0);
        void stop(void);
        void join(void);

        void closeAccepter(void);
        void closeSocket(Socket *sock);

        int errorCode(void) const { return _errCode; }
        const std::string& errorString(void) const { return _errString; }

    private:
		friend class Socket;
		friend class TcpThread;

        bool createAddtionalWorkers(int addtionalWorkers);
        static void onAccept(evutil_socket_t, struct sockaddr *, int, void *);
        void doAccept(evutil_socket_t, struct sockaddr *, int, void *);
        TcpThread *findWorker(void);

        void uninitialize(void);


        typedef boost::unordered_map<int, Socket*>   SocketMap;

        std::auto_ptr<ServerSocket> _accepter;
        volatile int _connIdGen;
        SocketMap _connections;
        Mutex _connectionsLock;
        std::auto_ptr<SocketEventHandlerFactory> _socketFactory;
        std::auto_ptr<TcpThread> _mainThread;
        int _addtionalThreadNum;
        TcpThread **_addtionalThreads;
        int _errCode;
        std::string _errString;
        ThreadPool _pool;
		volatile bool _stopping;
        DISALLOW_COPY_AND_ASSIGN(TcpServer);
    };

}}

#endif // SHARED_NET_TCPSERVER_H_
